
'use strict'

/**
 * 
 * 鸭子接口, 函数asboy仅用于装饰其他函数回调的boy实例, 被asboy装饰的boy_container实例(如let boy_container2 = asboy(boy_container))和boy实例表现为一致的外部行为
 * 该函数不持有任何状态, 不依赖于其他模块, 可以将该函数拷贝到任意位置;也可以重复定义(当然要确保不再同一个作用域定义)
 * 
 * 同理, boy_container2.IModel可作为父类装饰Model, 用于注册Model,boy_container2.register
 * 
 * 示例：
 * 
 * module.exports = function(boy){
 *     let boy2 = asboy(boy)
 *     // boy2和boy表现为相同的特征, 他的作用类似ts中的类型标注, boy:IBoy
 *     // boy.register(class{}) 和 boy2.register(class extends boy2.Model{}) 这两种写法是等价的
 *     // 只是第二种方式为回调的boy实例提供友好的接口
 * }
 * 
 * 
*/

class IBoyContainer{
    /**
     * IBoyContainer
     * 
     * @class
    */
    constructor(boy){
        this.boy = boy
        this.IModel = IModel
        let _exports = this.boy._exports || {}
        for(let key in _exports){
            this[key] = this.boy[key]
        }
    }
    _apply(fun_name, args){
        let res = this.boy[fun_name].apply(this.boy, args)
        return 'BoyContainer' === res.__name ? this : res
    }
    register(model, model_name){
        /**
         * 
         * register a Model
         * 
         * @param {IModel} model - a model
         * @param {string|undefined} model_name - the param will read throw IBoyContainer.boy.__current_model_name if not provide
         * @return {IBoyContainer}
         */
        return this._apply('register', [model, model_name])
    }
    getWrapper(Model_name){
        
    }
    allModels(){
        /**
         * 返回注册的所有模型名
         * 
         * @return {Array.<string>}
        */
       return this._apply('allModels', [])
    }
    each(callback){
        return this._apply('each', args)
    }
    get(boy_name){
        return this._apply('get', args)
    }
    create(model_name, boy_name, config_name, extra_config, mount_point, mount_param){
        /**
         * 
         * 创建一个boy实例, 通常情况下外部不应该调用该方法
         * 因为这个方法形参太多了, 然而, 这些形参应该由容器自动维护
         * 
         * 请参加文档
         * @see {@link start}
         * 
         * @param {string} model_name
         * @param {string} boy_name
         * @param {string} config_name
         * @param {object} extra_config - 为默认的config提供额外的参数, 只接受被IBoyContainer.f或IBoyContainer.ef强制标记的对象 
         * @param {IModel|undefined} mount_point - 根节点没有挂载点
         * @return {void}
         * 
        */
        return this._apply('create', [model_name, boy_name, config_name, extra_config, mount_point, mount_param])
    }
    createByCmd(cmd){
    }
    createByCmd(){
    }
    env(env){
        /**
         * set env val
         * 
         * @param {object} env - set env, the value will overwrite old value
         * @return {IBoyContainer} 
        */
        return this._apply('env', [env])
    }
    init(){

    }
}

class IModel{
    /**
     * @class
    */
    $registerInitListener(){
    }
    $registerLoginListener(){
    }
    $registerDestoryListener(){
    }

    $container(){
    }
    $wrapper(){
    }
    $index(){
    }
    $mount(){
    }

    // ...crud
    $json(){
    }
    $set(){
    }
    $get(){
    }
    $create(){
    }
    $destory(){
    }
    $insert(){
    }
    $each(){
    }
    $remove(){
    }

    // 需要服务器支持
    async $clone(){
    }
    async $commit(){
    }

    // 刷新页面, angularjs不需要手动刷新
    async $refresh(){
    }

}


function asboy(boy){
    
    return new IBoyContainer(boy)
}
